import {BaseNode, type BaseNodeParams} from "./baseNode";
import { getFont } from "@/utils/canvasTools";


export interface textNodeParam extends BaseNodeParams{
    textStr: string;
    textStyle: {
        fontSize: number;
        color: string;
        direction: 'horizontal' | 'vertical';
        bold: boolean;
        italic: boolean;
        underline: boolean;
        letterSpacing: number;
        lineHeight: number;
        scale: number;
        fontFamily: string;
        flipX: 1 | -1 ;
        flipY: 1 | -1;
    };
}

export class TextNode extends BaseNode {

    public _textStr: string;
    public _textStyle: {
        fontSize: number;
        color: string;
        direction: 'horizontal' | 'vertical';
        bold: boolean;
        italic: boolean;
        underline: boolean;
        letterSpacing: number;
        lineHeight: number;
        scale: number;
        fontFamily: string;
        flipX: 1 | -1 ;
        flipY: 1 | -1;
    };

    constructor(param: textNodeParam) {
        // // console.log('TextNode constructor',  param)
        const {textStr, ...rst} = param;

        super({...param, type: 'text',});

        this._textStr = textStr;
        this._textStyle = param.textStyle;
    }

    updateTxt(param: textNodeParam) {
        const {textStr, ...rst} = param;

        this._textStr = textStr;
        this.width = param.width;
        this.height = param.height;
        this.x = param.x;
        this.y = param.y;
        this.flipX =  param.textStyle.flipX;
        this.flipY =  param.textStyle.flipY;
        this._textStyle = {
            ...param.textStyle,
            width: param.width,
            height: param.height,
            x: param.x,
            y: param.y
        };

        this.updateBox({
            x: param.x,
            y: param.y,
            width: param.width,
            height: param.height,
        })
    }

    /**
     * 渲染
     * @param ctx
     */
    async render(ctx: any) {
       await this.renderText(ctx, this.x, this.y);
    }

    /**
     * 渲染文本
     * @param ctx
     */
    renderText(ctx: any, x, y) {
        ctx.save();
        // 设置文字样式
        ctx.font = getFont(this._textStyle);
        ctx.fillStyle = this._textStyle.color;
        ctx.textBaseline = 'top';
        ctx.letterSpacing = `${this._textStyle.letterSpacing}px`;

        const w = this.width / 2;
        const h = this.height / 2;
        const PAD =  4;

        const textStrArr = this._textStr.split('\n');
        // 单行文本高度
        const lineHeight =  this._textStyle.lineHeight * this._textStyle.fontSize;

        const scaleX = this.flipX;
        const scaleY = this.flipY;

        // console.error('renderText 方向', this._textStyle.direction)
        // 绘制文字
        if (this._textStyle.direction === 'horizontal') {
            ctx.translate(x + w, y +h);
            ctx.rotate(this.rotation * Math.PI / 180);
            ctx.scale(scaleX * this.scale, scaleY * this.scale);

            let currentY = -h;
            for(let i = 0; i < textStrArr.length; i++) {
                this.fillTextWithSpacing(ctx, textStrArr[i], -w + this._textStyle.leftX[i], currentY, this._textStyle.letterSpacing)

                currentY += lineHeight;
            }

            // 绘制下划线
            if (this._textStyle.underline) {
                const textWidth = this.width;
                ctx.beginPath();
                ctx.moveTo(
                  -w,
                  currentY,
                );
                ctx.lineTo(
                  -w + textWidth,
                  currentY,
                );
                ctx.strokeStyle = this._textStyle.color;
                ctx.stroke();
            }
        } else {
            // // console.log('纵向排列>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
            ctx.translate(x + w, y + h);
            ctx.rotate(this.rotation * Math.PI / 180);
            ctx.scale(scaleX * this.scale, scaleY * this.scale);

            // 纵向排列（每个字符单独绘制）
            let currentX = -w;
            for(let i = 0; i < textStrArr.length; i++) {
                const chars = textStrArr[i].split('');
                let currentY = -h + this._textStyle.leftX[i];
                let maxChart = 0;
                chars.forEach((char) => {
                    this.fillTextWithSpacing(ctx, char, currentX, currentY, this._textStyle.letterSpacing)
                    currentY += lineHeight + this._textStyle.letterSpacing;

                    maxChart = Math.max(maxChart, ctx.measureText(char).width);
                });
                // currentX += this._textStyle.fontSize ;
                currentX += maxChart
            }
        }
        ctx.restore();
    }


    /**
     * 渲染离屏文本
     */
    renderOffScreenCanvas() {
        const offScreenCtx = super.getOffScreenCanvas();
        this.renderText(offScreenCtx, 0 , 0);
    }

    public getOffScreenCanvasImage() {
        this.renderOffScreenCanvas();
        // console.log(this._offScreenCanvas.toDataURL())

        return this.getOffScreenCanvasImageMark(); // super._offScreenCtx.getImageData(this.x, this.y, this.width, this.height);
    }
    /**
     * 绘制带间距的文字
     * @param ctx
     * @param {string} text 要绘制的文字
     * @param {number} x 绘制的起始位置 x
     * @param {number} y 绘制的起始位置 y
     * @param {number} spacing 文字间距
     */
    fillTextWithSpacing(ctx, text, x, y, spacing = 0) {
        // 如果间距为0,则直接调用原生方法以节省性能
        if (spacing === 0) {
            ctx.fillText(text, x, y);
            return;
        }

        let currentX = x;
        let currentY = y;
        // 对每个字符单独渲染
        for (let i = 0; i < text.length; i++) {
            const char = text[i];
            ctx.fillText(char, currentX, y);
            // 累计已占用宽度 = 当前字符宽度 + 间距
            currentX += ctx.measureText(char).width + spacing;
        }
    };

    public  exportData() {
        return {
            ...super.exportData(),
            textStr: this._textStr,
            textStyle: this._textStyle,
        };
    }
}
